home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / shells / bashsrc.zoo / execute_cmd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-05  |  42.9 KB  |  1,684 lines

  1. /* execute_command.c -- Execute a COMMAND structure. */
  2.  
  3. /* Copyright (C) 1989 Free Software Foundation, Inc.
  4.  
  5. This file is part of GNU Bash, the Bourne Again SHell.
  6.  
  7. Bash is free software; you can redistribute it and/or modify it under
  8. the terms of the GNU General Public License as published by the Free
  9. Software Foundation; either version 1, or (at your option) any later
  10. version.
  11.  
  12. Bash is distributed in the hope that it will be useful, but WITHOUT ANY
  13. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  15. for more details.
  16.  
  17. You should have received a copy of the GNU General Public License along
  18. with Bash; see the file COPYING.  If not, write to the Free Software
  19. Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
  20.  
  21. #include <stdio.h>
  22. #include <sys/types.h>
  23. #ifndef SONY
  24. #include <fcntl.h>
  25. #endif
  26. #include <sys/file.h>
  27. #include <sys/stat.h>
  28. #include <signal.h>
  29.  
  30. #ifndef SIGABRT
  31. #define SIGABRT SIGIOT
  32. #endif
  33.  
  34. #include <sys/param.h>
  35. #include <errno.h>
  36.  
  37. #include "shell.h"
  38. #include "y.tab.h"
  39. #include "builtins.h"
  40. #include "flags.h"
  41. #include "hash.h"
  42.  
  43. #ifdef JOB_CONTROL
  44. #include "jobs.h"
  45. #endif
  46.  
  47. #ifdef ALIAS
  48. #include "alias.h"
  49. #endif
  50.  
  51. extern int breaking, continuing, loop_level;
  52. extern int errno, sys_nerr;
  53. extern char *sys_errlist[];
  54.  
  55. #ifdef SYSV
  56. extern int last_made_pid;
  57. #endif
  58.  
  59. extern WORD_LIST *expand_words (), *expand_word ();
  60.  
  61. /* The value returned by the last synchronous command. */
  62. int last_command_exit_value = 0;
  63.  
  64. /* The list of redirections to preform which will undo the redirections
  65.    that I made in the shell. */
  66. REDIRECT *redirection_undo_list = (REDIRECT *)NULL;
  67.  
  68. /* Execute the command passed in COMMAND.  COMMAND is exactly what
  69.    read_command () places into GLOBAL_COMMAND.  See "shell.h" for the
  70.    details of the command structure.
  71.  
  72.    EXECUTION_SUCCESS or EXECUTION_FAILURE are the only possible
  73.    return values.  Executing a command with nothing in it returns
  74.    success. */
  75. execute_command (command)
  76.      COMMAND *command;
  77. {
  78.   /* Just do the command, but not asynchronously. */
  79.   return (execute_command_internal (command, 0, NO_PIPE, NO_PIPE));
  80. }
  81.  
  82. /* Returns 1 if TYPE is a shell control structure type. */
  83. int
  84. shell_control_structure (type)
  85.      enum command_type type;
  86. {
  87.   switch (type)
  88.     {
  89.     case cm_for:
  90.     case cm_case:
  91.     case cm_while:
  92.     case cm_until:
  93.     case cm_if:
  94.     case cm_group:
  95.       return (1);
  96.  
  97.     default:
  98.       return (0);
  99.     }
  100. }
  101.  
  102. execute_command_internal (command, asynchronous, pipe_in, pipe_out)
  103.      COMMAND *command;
  104.      int asynchronous;
  105.      int pipe_in, pipe_out;
  106. {
  107.   int exec_result;
  108.   REDIRECT *my_undo_list = (REDIRECT *)NULL;
  109.  
  110.   if (!command || breaking || continuing)
  111.     return (EXECUTION_SUCCESS);
  112.  
  113.   /* If a command was being explicitly run in a subshell, or if it is
  114.      a shell control-structure, and it has a pipe, then we do the command
  115.      in a subshell. */
  116.  
  117.   if (command->subshell ||
  118.       (shell_control_structure (command->type) &&
  119.        (pipe_out != NO_PIPE || pipe_in != NO_PIPE || asynchronous)))
  120.     {
  121.       int paren_pid;
  122.  
  123.       /* Fork a subshell, turn off the subshell bit, turn off job
  124.      control and call execute_command () on the command again. */
  125.       paren_pid = make_child (savestring (make_command_string (command)),
  126.                   asynchronous);
  127.       if (paren_pid == 0)
  128.     {
  129.       extern int interactive, login_shell;
  130.  
  131.       command->subshell = 0;
  132.  
  133.       /* Don't fork again, we are already in a subshell. */
  134.       asynchronous = 0;
  135.  
  136.       /* Subshells are neither login nor interactive. */
  137.       login_shell = interactive = 0;
  138.  
  139. #ifdef JOB_CONTROL
  140.       /* Delete all traces that there were any jobs running.  This is
  141.          only for subshells. */
  142.       without_job_control ();
  143. #endif
  144.       do_piping (pipe_in, pipe_out);
  145.       if (command->redirects)
  146.         if (!(do_redirections (command->redirects, 1, 0) == 0))
  147.           exit (EXECUTION_FAILURE);
  148.       exit (execute_command_internal
  149.          (command, asynchronous, NO_PIPE, NO_PIPE));
  150.     }
  151.       else
  152.     {
  153.       close_pipes (pipe_in, pipe_out);
  154.  
  155.       /* If we are part of a pipeline, and not the end of the pipeline,
  156.          then we should simply return and let the last command in the
  157.          pipe be waited for.  If we are not in a pipeline, or are the
  158.          last command in the pipeline, then we wait for the subshell
  159.          and return its exit status as usual. */
  160.       if (pipe_out != NO_PIPE)
  161.         return (EXECUTION_SUCCESS);
  162.       
  163.       stop_pipeline (asynchronous, (COMMAND *)NULL);
  164.  
  165.       if (!asynchronous)
  166.         return (last_command_exit_value = wait_for (paren_pid));
  167.       else
  168.         {
  169.           extern int interactive;
  170.           if (interactive)
  171.         describe_pid (paren_pid);
  172.           return (EXECUTION_SUCCESS);
  173.         }
  174.     }
  175.     }
  176.  
  177.   /* Handle WHILE FOR CASE etc. with redirections.  (Also '&' input
  178.      redirection.)  */
  179.   do_redirections (command->redirects, 1, 1);
  180.   my_undo_list = (REDIRECT *)copy_redirects (redirection_undo_list);
  181.  
  182.   switch (command->type)
  183.     {
  184.     case cm_for:
  185.       exec_result = execute_for_command (command->value.For);
  186.       break;
  187.  
  188.     case cm_case:
  189.       exec_result = execute_case_command (command->value.Case);
  190.       break;
  191.  
  192.     case cm_while:
  193.       exec_result = execute_while_command (command->value.While);
  194.       break;
  195.  
  196.     case cm_until:
  197.       exec_result = execute_until_command (command->value.While);
  198.       break;
  199.  
  200.     case cm_if:
  201.       exec_result = execute_if_command (command->value.If);
  202.       break;
  203.  
  204.     case cm_group:
  205.       if (asynchronous)
  206.     {
  207.       command->subshell = 1;
  208.       exec_result =
  209.         execute_command_internal (command, 1, pipe_in, pipe_out);
  210.     }
  211.       else
  212.     {
  213.       exec_result =
  214.         execute_command_internal (command->value.Group->command,
  215.                       asynchronous, pipe_in, pipe_out);
  216.     }
  217.       break;
  218.  
  219.     case cm_simple:
  220.       {
  221.     extern int last_asynchronous_pid, last_made_pid;
  222.     int last_pid = last_made_pid;
  223.     
  224. #ifdef JOB_CONTROL
  225.     extern int already_making_children;
  226. #endif 
  227.     exec_result =
  228.       execute_simple_command (command->value.Simple, pipe_in, pipe_out,
  229.                   asynchronous);
  230.  
  231.     /* If we forked to do the command, then we must
  232.        wait_for() the child. */
  233. #ifdef JOB_CONTROL
  234.     if (already_making_children && pipe_out == NO_PIPE)
  235. #else
  236.       if (pipe_out == NO_PIPE)
  237. #endif
  238.         {
  239.           if (last_pid != last_made_pid)
  240.         {
  241.           stop_pipeline (asynchronous, (COMMAND *)NULL);
  242.  
  243.           if (asynchronous)
  244.             {
  245.               extern int interactive;
  246.  
  247.               if (interactive)
  248.             describe_pid (last_made_pid);
  249.             }
  250.           else
  251.             exec_result = wait_for (last_made_pid);
  252.         }
  253.         }
  254.       }
  255.       break;
  256.  
  257.     case cm_connection:
  258.       switch (command->value.Connection->connector)
  259.     {
  260.       /* Do the first command asynchronously. */
  261.     case '&':
  262.       {
  263.         COMMAND *tc = command->value.Connection->first;
  264. #ifndef JOB_CONTROL
  265.         {
  266.           REDIRECT *tr = 
  267.         make_redirection (0, r_inputa_direction,
  268.                   make_word ("/dev/null"));
  269.           tr->next = tc->redirects;
  270.           tc->redirects = tr;
  271.         }
  272. #endif                /* !JOB_CONTROL */
  273.         exec_result = execute_command_internal (tc, 1, pipe_in, pipe_out);
  274.         if (command->value.Connection->second)
  275.           exec_result =
  276.         execute_command_internal (command->value.Connection->second,
  277.                       asynchronous, pipe_in, pipe_out);
  278.       }
  279.       break;
  280.  
  281.     case ';':
  282.       /* Just call execute command on both of them. */
  283.       execute_command (command->value.Connection->first);
  284.       exec_result =
  285.         execute_command_internal (command->value.Connection->second,
  286.                       asynchronous, pipe_in, pipe_out);
  287.       break;
  288.  
  289.     case '|':
  290.       {
  291.         /* Make a pipeline between the two commands. */
  292.         int fildes[2];
  293.         if (pipe (fildes) < 0)
  294.           {
  295.         report_error ("Pipe error %d", errno);
  296.         exec_result = EXECUTION_FAILURE;
  297.           }
  298.         else
  299.           {
  300.         execute_command_internal (command->value.Connection->first,
  301.                       asynchronous, pipe_in, fildes[1]);
  302.         exec_result =
  303.           execute_command_internal (command->value.Connection->second,
  304.                         asynchronous, fildes[0], pipe_out);
  305.           }
  306.       }
  307.       break;
  308.  
  309.     case AND_AND:
  310.       /* Execute the first command.  If the result of that is successful,
  311.          then execute the second command, otherwise return. */
  312.       if (execute_command (command->value.Connection->first)
  313.           != EXECUTION_FAILURE)
  314.         exec_result = execute_command (command->value.Connection->second);
  315.       else exec_result = EXECUTION_FAILURE;
  316.       break;
  317.  
  318.     case OR_OR:
  319.       /* Execute the first command.  If the result of that is successfull,
  320.          then return, otherwise execute the second command. */
  321.       if (execute_command (command->value.Connection->first)
  322.           == EXECUTION_FAILURE)
  323.         exec_result =  execute_command (command->value.Connection->second);
  324.       else exec_result = EXECUTION_SUCCESS;
  325.       break;
  326.     
  327.     default:
  328.       programming_error ("Bad connector `%d'!",
  329.                  command->value.Connection->connector);
  330.       longjmp (top_level, DISCARD);
  331.       break;
  332.     }
  333.       break;
  334.       
  335.     case cm_function_def:
  336.       exec_result = intern_function (command->value.Function_def->name,
  337.                      command->value.Function_def->command);
  338.       break;
  339.  
  340.     default:
  341.       programming_error ("execute_command: Bad command type `%d'!",
  342.              command->type);
  343.     }
  344.  
  345.   if (my_undo_list)
  346.     {
  347.       do_redirections (my_undo_list, 1, 0);
  348.       dispose_redirects (my_undo_list);
  349.     }
  350.   return (last_command_exit_value = exec_result);
  351. }
  352.  
  353. /* Execute a FOR command.  The syntax is: FOR word_desc IN word_list;
  354.    DO command; DONE */
  355. execute_for_command (for_command)
  356.      FOR_COM *for_command;
  357. {
  358.   /* I just noticed that the Bourne shell leaves word_desc bound to the
  359.      last name in word_list after the FOR statement is done.  This seems
  360.      wrong to me; I thought that the variable binding should be lexically
  361.      scoped, i.e. only would last the duration of the FOR command.  This
  362.      behaviour can be gotten by turning on the lexical_scoping switch. */
  363.  
  364.   extern int breaking, continuing;
  365.   register WORD_LIST *releaser, *list;
  366.   WORD_DESC *temp = for_command->name;
  367.   char *identifier;
  368.   SHELL_VAR *old_value;        /* Remember the old value of x. */
  369.  
  370.   if (!check_identifier (temp))
  371.     return (EXECUTION_FAILURE);
  372.  
  373.   loop_level++;
  374.   identifier = temp->word;
  375.  
  376.   list = releaser = expand_words (for_command->map_list, 0);
  377.  
  378.   if (lexical_scoping)
  379.     old_value = copy_variable (find_variable (identifier));
  380.  
  381.   while (list)
  382.     {
  383.       QUIT;
  384.       bind_variable (identifier, list->word->word);
  385.       execute_command (for_command->action);
  386.       QUIT;
  387.  
  388.       if (breaking)
  389.     {
  390.       breaking--; 
  391.       break;
  392.     }
  393.  
  394.       if (continuing)
  395.     {
  396.       continuing--;
  397.       if (continuing)
  398.         break;
  399.     }
  400.  
  401.       list = list->next;
  402.     }
  403.   dispose_words (releaser);
  404.  
  405.   loop_level--;
  406.   
  407.   if (lexical_scoping)
  408.     {
  409.       if (!old_value)
  410.     {
  411.       makunbound (identifier);
  412.     }
  413.       else
  414.     {
  415.       SHELL_VAR *new_value;
  416.       if (function_p (old_value))
  417.         bind_function (identifier, old_value->function);
  418.       else
  419.         bind_variable (identifier, old_value->value);
  420.     
  421.       new_value = find_variable (identifier);
  422.       new_value->attributes = old_value->attributes;
  423.     }
  424.       dispose_variable (old_value);
  425.     }
  426.   return (EXECUTION_SUCCESS);
  427. }
  428.  
  429. /* Execute a CASE command.  The syntax is: CASE word_desc IN pattern_list ESAC.
  430.    The pattern_list is a linked list of pattern clauses; each clause contains
  431.    some patterns to compare word_desc against, and an associated command to
  432.    execute. */
  433. execute_case_command (case_command)
  434.      CASE_COM *case_command;
  435. {
  436.   extern dispose_words ();
  437.   WORD_LIST *wlist = expand_word (case_command->word, 0);
  438.   PATTERN_LIST *clauses = case_command->clauses;
  439.   register WORD_LIST *list;
  440.   char *word = (wlist) ? wlist->word->word : "";
  441.  
  442.   add_unwind_protect (dispose_words, wlist);
  443.   while (clauses)
  444.     {
  445.       QUIT;
  446.       list = clauses->patterns;
  447.       while (list)
  448.     {
  449.       WORD_LIST *es = expand_word (list->word, 0);
  450.       char *pattern = (es) ? es->word->word : "";
  451.  
  452.       if (glob_match (pattern, word, 0))
  453.         {
  454.           dispose_words (es);
  455.           execute_command (clauses->action);
  456.           goto exit_command;
  457.         }
  458.       dispose_words (es);
  459.       list = list->next;
  460.       QUIT;
  461.     }
  462.       clauses = clauses->next;
  463.     }
  464.  exit_command:
  465.   remove_unwind_protect ();
  466.   dispose_words (wlist);
  467.   return (EXECUTION_SUCCESS);
  468. }
  469.  
  470. /* The WHILE command.  Syntax: WHILE test DO action; DONE.
  471.    Repeatedly execute action while executing test produces
  472.    EXECUTION_SUCCESS. */
  473. execute_while_command (while_command)
  474.      WHILE_COM *while_command;
  475. {
  476.   extern int breaking;
  477.   extern int continuing;
  478.   int commands_executed = 0;
  479.  
  480.   loop_level++;
  481.  
  482.   while (execute_command (while_command->test) == EXECUTION_SUCCESS)
  483.     {
  484.       QUIT;
  485.       commands_executed = 1;
  486.       execute_command (while_command->action);
  487.       QUIT;
  488.  
  489.       if (breaking)
  490.     {
  491.       breaking--;
  492.       break;
  493.     }
  494.  
  495.       if (continuing)
  496.     {
  497.       continuing--;
  498.       if (continuing)
  499.         break;
  500.     }
  501.     }
  502.   loop_level--;
  503.   return ((commands_executed == 1) ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
  504. }
  505.  
  506. /* UNTIL is just like WHILE except that the test result is negated. */
  507. execute_until_command (while_command)
  508.      WHILE_COM *while_command;
  509. {
  510.   extern int breaking;
  511.   extern int continuing;
  512.   int commands_executed = 0;
  513.  
  514.   loop_level++;
  515.   while (execute_command (while_command->test) != EXECUTION_SUCCESS)
  516.     {
  517.       QUIT;
  518.       commands_executed = 1;
  519.       execute_command (while_command->action);
  520.       QUIT;
  521.  
  522.       if (breaking)
  523.     {
  524.       breaking--;
  525.       break;
  526.     }
  527.  
  528.       if (continuing)
  529.     {
  530.       continuing--;
  531.       if (continuing)
  532.         break;
  533.     }
  534.  
  535.     }
  536.   loop_level--;
  537.   return (commands_executed);
  538. }
  539.  
  540. /* IF test THEN command [ELSE command].
  541.    IF also allows ELIF in the place of ELSE IF, but
  542.    the parser makes *that* stupidity transparent. */
  543. execute_if_command (if_command)
  544.      IF_COM *if_command;
  545. {
  546.   if (execute_command (if_command->test) == EXECUTION_SUCCESS)
  547.     {
  548.       QUIT;
  549.       return (execute_command (if_command->true_case));
  550.     }
  551.   else
  552.     {
  553.       QUIT;
  554.       return (execute_command (if_command->false_case));
  555.     }
  556. }
  557.  
  558. Function *
  559. find_shell_builtin (string)
  560.      char *string;
  561. {
  562.   int i = 0;
  563.   while (shell_builtins[i].name)
  564.     {
  565.       if (shell_builtins[i].enabled &&
  566.       strcmp (shell_builtins[i].name, string) == 0)
  567.     return (shell_builtins[i].function);
  568.       i++;
  569.     }
  570.   return ((Function *)NULL);
  571. }
  572.  
  573. /* The name of the command that is currently being executed.
  574.    `test' needs this, for example. */
  575. char *this_command_name;
  576.  
  577. /* For catching RETURN in a function. */
  578. int return_catch_flag = 0;
  579. int return_catch_value;
  580. jmp_buf return_catch;
  581.  
  582. /* The meaty part of all the executions.  We have to start
  583.    hacking the real execution of commands here.  Fork a process,
  584.    set things up, execute the command. */
  585. execute_simple_command (simple_command, pipe_in, pipe_out, async)
  586.      SIMPLE_COM *simple_command;
  587.      int pipe_in, pipe_out;
  588. {
  589.   WORD_LIST *expand_words ();
  590.   WORD_LIST *words;
  591.  
  592.   /* Remember what this command line looks like at invocation. */
  593.   extern int command_string_index;
  594.   extern char *the_printed_command;
  595.   char *command_line;
  596.   int first_word_quoted;
  597.  
  598.   command_string_index = 0;
  599.   print_simple_command (simple_command);
  600.   command_line = (char *)alloca (1 + strlen (the_printed_command));
  601.   strcpy (command_line, the_printed_command);
  602.  
  603.   first_word_quoted =
  604.     (simple_command->words? simple_command->words->word->quoted : 0);
  605.  
  606.   words = expand_words (simple_command->words);
  607.  
  608.   /* It is possible for WORDS not to have anything left in it.
  609.      Perhaps all the words consisted of `$foo', and there was
  610.      no variable `$foo'. */
  611.   if (words)
  612.     {
  613.       extern Function *last_shell_builtin, *this_shell_builtin;
  614.       extern int ignore_function_references;
  615.       Function *builtin;
  616.       SHELL_VAR *var = find_variable (words->word->word);
  617.       char *auto_resume_value;
  618.  
  619.       if (echo_command_at_execute)
  620.     {
  621.       extern char *string_list (), *indirection_level_string ();
  622.       char *line = string_list (words);
  623.  
  624.       if (line && *line)
  625.         fprintf (stderr, "%s%s\n", indirection_level_string (), line);
  626.  
  627.       if (line)
  628.         free (line);
  629.     }
  630.  
  631.       if (ignore_function_references)
  632.     var = (SHELL_VAR *)NULL;
  633.  
  634.       QUIT;
  635. #ifdef JOB_CONTROL
  636.       /* Is this command a job control related thing? */
  637.       if (words->word->word[0] == '%')
  638.     {
  639.       this_command_name = "fg";
  640.       return (fg_builtin (words));
  641.     }
  642.  
  643.       /* One other possiblilty.  The user may want to resume an existing job.
  644.      If they do, find out whether this word is a candidate for a running
  645.      job. */
  646.       if ((auto_resume_value = get_string_value ("auto_resume")) &&
  647.       !first_word_quoted &&
  648.       !words->next &&
  649.       words->word->word[0] &&
  650.       !simple_command->redirects &&
  651.       pipe_in == NO_PIPE &&
  652.       pipe_out == NO_PIPE &&
  653.       !async)
  654.     {
  655.       char *word = words->word->word;
  656.       register int i, wl = strlen (word), exact;
  657.  
  658.       exact = strcmp (auto_resume_value, "exact") == 0;
  659.       for (i = job_slots - 1; i > -1; i--)
  660.         {
  661.           if (jobs[i])
  662.         {
  663.           register PROCESS *p = jobs[i]->pipe;
  664.           do
  665.             {
  666.               if ((exact && strcmp (p->command, word) == 0) ||
  667.               strncmp (p->command, word, wl) == 0)
  668.             {
  669.               dispose_words (words);
  670.               return (start_job (i, 1));
  671.             }
  672.               p = p->next;
  673.             }
  674.           while (p != jobs[i]->pipe);
  675.         }
  676.         }
  677.     }
  678. #endif
  679.  
  680.       /* Not a running job.  Do normal command processing. */
  681.       maybe_make_export_env ();
  682.       QUIT;
  683.  
  684.       /* Remember the name of this command globally. */
  685.       this_command_name = words->word->word;
  686.  
  687.       /* This command could be a shell builtin or a user-defined function.
  688.      If so, and we have pipes, then fork a subshell in here.  Else, just
  689.      do the command. */
  690.  
  691.       if (var && function_p (var))
  692.     builtin = (Function *)NULL;
  693.       else
  694.     {
  695.       builtin = find_shell_builtin (words->word->word);
  696.       last_shell_builtin = this_shell_builtin;
  697.       this_shell_builtin = builtin;
  698.     }
  699.  
  700.       if (builtin || (var && function_p (var)))
  701.     {
  702.       if ((pipe_in != NO_PIPE) || (pipe_out != NO_PIPE) || async)
  703.         {
  704. #ifdef JOB_CONTROL
  705.           extern int job_control;
  706.           int old_job_control = job_control;
  707.  
  708.           /* Turn off job control before we fork the subshell. */
  709.           set_job_control (0);
  710. #endif /* JOB_CONTROL */
  711.           if (make_child (savestring (command_line), async) == 0)
  712.         {
  713.           do_piping (pipe_in, pipe_out);
  714.  
  715.           if (do_redirections (simple_command->redirects, 1, 0) == 0)
  716.             {
  717.               if (builtin)
  718.             exit ((*builtin) (words->next));
  719.               else
  720.             {
  721.               COMMAND *tc = (COMMAND *)copy_command (function_cell (var));
  722.               int result;
  723.               extern int variable_context;
  724.  
  725.               remember_args (words->next, 1);
  726. #ifdef JOB_CONTROL
  727.               stop_pipeline (async, (COMMAND *)NULL);
  728. #endif
  729.               variable_context++;
  730.               return_catch_flag++;
  731.               result = execute_command (tc);
  732.               dispose_command (tc);
  733.               variable_context--;
  734.               exit (result);
  735.             }
  736.             }
  737.           else
  738.             {
  739.               exit (EXECUTION_FAILURE);
  740.             }
  741.         }
  742.           else
  743.         {
  744.           close_pipes (pipe_in, pipe_out);
  745. #ifdef JOB_CONTROL
  746.           set_job_control (old_job_control);
  747. #endif
  748.           return (EXECUTION_SUCCESS);
  749.         }
  750.         }
  751.       else
  752.         {
  753.           int result = EXECUTION_FAILURE;
  754.  
  755.            if (do_redirections (simple_command->redirects, 1, 1) == 0)
  756.          {
  757.           REDIRECT *saved_undo_list = redirection_undo_list;
  758.  
  759.           redirection_undo_list = (REDIRECT *)NULL;
  760.  
  761.            if (builtin)
  762.              result = ((*builtin) (words->next));
  763.            else
  764.              {
  765.                int return_val;
  766.                extern int dispose_command (), pop_context ();
  767.               jmp_buf old_return_catch;
  768.                COMMAND *tc;
  769.               
  770.               tc = (COMMAND *)copy_command (function_cell (var));
  771.  
  772.                push_context ();
  773.                begin_unwind_frame ("function_calling");
  774.                add_unwind_protect (pop_context, (char *)NULL);
  775.                add_unwind_protect (dispose_command, (char *)tc);
  776.  
  777.               /* Note the second argument of "1", meaning that
  778.               we discard the current value of "$*"!  This
  779.               is apparently the right thing. */
  780.               remember_args (words->next, 1);
  781.  
  782.                return_catch_flag++;
  783.               bcopy ((char *)return_catch, (char *)old_return_catch,
  784.                  sizeof (jmp_buf));
  785.                return_val =  setjmp (return_catch);
  786.  
  787.                if (return_val)
  788.             result = return_catch_value;
  789.               else
  790.             result = execute_command (tc);
  791.  
  792.                run_unwind_frame ("function_calling");
  793.                return_catch_flag--;
  794.               bcopy ((char *)old_return_catch, (char *)return_catch,
  795.                  sizeof (jmp_buf));
  796.              }
  797.           redirection_undo_list = saved_undo_list;
  798.          }
  799.           do_redirections (redirection_undo_list, 1, 0);
  800.           dispose_words (words);
  801.           return (result);
  802.         }
  803.     }
  804.  
  805.       {
  806.     /* Hopefully this command is defined in a disk file somewhere.
  807.        
  808.        1) fork ()
  809.        2) connect pipes
  810.        3) close file descriptors 3-NOFILE
  811.        4) look up the command
  812.        5) do redirections
  813.        6) execve ()
  814.        7) If the execve failed, see if the file has executable mode set.
  815.        If so, and it isn't a directory, then execute its contents as
  816.        a shell script.
  817.        
  818.        Note that the filename hashing stuff has to take place up here,
  819.        in the parent.  This is probably why the Bourne style shells
  820.        don't handle it, since that would require them to go through
  821.        this gnarly hair, for no good reason.
  822.        */
  823.  
  824.     char **make_word_array (), *find_user_command (),
  825.     *find_hashed_filename ();
  826.  
  827.     char *hashed_file, *command, **args;
  828.  
  829.     hashed_file = find_hashed_filename (words->word->word);
  830.  
  831.     if (hashed_file)
  832.       command = savestring (hashed_file);
  833.     else
  834.       {
  835.         command = find_user_command (words->word->word);
  836.         if (command && !hashing_disabled)
  837.           {
  838.         extern int dot_found_in_search;
  839.         if (!absolute_pathname (words->word->word))
  840.           remember_filename (words->word->word,
  841.                      command, dot_found_in_search);
  842.         /* Increase the number of hits to 1. */
  843.         find_hashed_filename (words->word->word);
  844.           }
  845.       }
  846.  
  847.     /* We have to make the child before we check for the non-existance
  848.        of COMMAND, since we want the error messages to be redirected. */
  849.       
  850.     if (make_child (savestring (command_line), async) == 0)
  851.       {
  852.         do_piping (pipe_in, pipe_out);
  853.         {
  854.           register int i;
  855.           for (i = 3; i < NOFILE; i++)
  856.         close (i);
  857.         }
  858.       
  859.         /* Execve expects the command name to be in args[0].  So we
  860.            leave it there, in the same format that the user used to
  861.            type it in. */
  862.         args = make_word_array (words);
  863.  
  864.         if (!command)
  865.           {
  866.         report_error ("%s: command not found", args[0]);
  867.         exit (EXECUTION_FAILURE);
  868.           }
  869.  
  870.         if (do_redirections (simple_command->redirects, 1, 0) == 0)
  871.           {
  872.         execve (command, args, export_env);
  873.  
  874.         /* If we get to this point, then start checking out the file.
  875.            Maybe it is something we can hack ourselves. */
  876.         {
  877.           struct stat finfo;
  878.           extern int errno;
  879.  
  880.           if (errno != ENOEXEC)
  881.             {
  882.               if ((stat (command, &finfo) == 0) &&
  883.               ((finfo.st_mode & S_IFMT) == S_IFDIR))
  884.             report_error ("%s: is a directory", args[0]);
  885.               else
  886.             file_error (command);
  887.         
  888.               exit (EXECUTION_FAILURE);
  889.             }
  890.           else
  891.             {
  892.               /* This file is executable.
  893.              If it begins with #!, then help out people
  894.              with losing operating systems.  Otherwise,
  895.              check to see if it is a binary file by seeing
  896.              if the first line (or upto 30 characters) are
  897.              in the ASCII set.
  898.              Execute the contents as shell commands. */
  899.               extern char *shell_name;
  900.               int larry = array_len (args) + 1;
  901.               int i, should_exec = 0;
  902.  
  903.               {
  904.             int fd = open (command, O_RDONLY);
  905.             if (fd != -1)
  906.               {
  907.                 unsigned char sample[80];
  908.                 int sample_len = read (fd, &sample[0], 80);
  909.  
  910.                 /* Is this supposed to be an executable script? */
  911.                 if (strncmp (sample, "#!", 2) == 0)
  912.                   {
  913.                 char *execname;
  914.                 int start;
  915.  
  916.                 for (i = 2;
  917.                      whitespace (sample[i]) && i < 80; i++);
  918.                 start = i;
  919.                 for (; !whitespace (sample[i]) &&
  920.                      sample[i] != '\n' && i < 80;
  921.                      i++);
  922.  
  923.                 execname = (char *)xmalloc (1 + (i - start));
  924.                 strncpy (execname, sample + start, i - start);
  925.                 execname[i - start] = '\0';
  926.  
  927.                 should_exec = 1;
  928.                 shell_name = execname;
  929.                   }
  930.                 else
  931.                   {
  932.                 if (sample_len != -1)
  933.                   {
  934.                     for (i = 0; i < sample_len; i++)
  935.                       {
  936.                     if (sample[i] == '\n')
  937.                       break;
  938.                     if (sample[i] > 128 || sample[i] < ' ')
  939.                       {
  940.                         if (sample[i] == '\t')
  941.                           continue;
  942.                         
  943.                         report_error ("%s: Cannot execute binary file", shell_name);
  944.                         exit (EXECUTION_FAILURE);
  945.                       }
  946.                       }
  947.                   }
  948.                   }
  949.                 close (fd);
  950.               }
  951.               }
  952. #ifdef JOB_CONTROL
  953.               /* Forget about the way that job control was working.
  954.              We are in a subshell. */
  955.               without_job_control ();
  956. #endif
  957. #ifdef ALIAS
  958.               /* Forget about any aliases that we knew of.
  959.              We are in a subshell. */
  960.               delete_all_aliases ();
  961. #endif
  962.  
  963.               /* Insert the name of this shell into the argument
  964.              list. */
  965.               args =
  966.             (char **)xrealloc (args, (1 + larry) * sizeof (char *));
  967.               for (i = larry - 1; i; i--)
  968.             args[i] = args[i - 1];
  969.  
  970.               args[0] = shell_name;
  971.               args[1] = command;
  972.               args[larry] = (char *)NULL;
  973.  
  974.               if (args[0][0] == '-')
  975.             args[0]++;
  976.  
  977.               if (should_exec)
  978.             {
  979.               struct stat finfo;
  980.               extern int errno;
  981.  
  982.               execve (shell_name, args, export_env);
  983.  
  984.               /* Oh, no!  We couldn't even exec this! */
  985.  
  986.               if ((stat (shell_name, &finfo) == 0) &&
  987.                   ((finfo.st_mode & S_IFMT) == S_IFDIR))
  988.                 report_error ("%s: is a directory", args[0]);
  989.               else
  990.                 file_error (shell_name);
  991.         
  992.               exit (EXECUTION_FAILURE);
  993.             }
  994.               else
  995.             exit (main (larry, args, export_env));
  996.             }
  997.         }
  998.           }
  999.         else
  1000.           {
  1001.         exit (EXECUTION_FAILURE);
  1002.           }
  1003.       }
  1004.     else
  1005.       {
  1006.         /* Make sure that the pipes are closed in the parent. */
  1007.         close_pipes (pipe_in, pipe_out);
  1008.         if (command)
  1009.           free (command);
  1010.       }
  1011.       }
  1012.       dispose_words (words);
  1013.       return (EXECUTION_SUCCESS);
  1014.     }
  1015.   else
  1016.     {
  1017.       /* Even if there aren't any command names, pretend to do the
  1018.      redirections that are specified.  The user expects the side
  1019.      effects to take place. */
  1020.       if (do_redirections (simple_command->redirects, 0, 0) == 0)
  1021.     return (last_command_exit_value);
  1022.       else
  1023.     return (EXECUTION_FAILURE);
  1024.     }
  1025. }
  1026.  
  1027. close_pipes (in, out)
  1028.      int in, out;
  1029. {
  1030.   if (in >= 0) close (in);
  1031.   if (out >= 0) close (out);
  1032. }
  1033.     
  1034.  
  1035. /* Redirect input and output to be from and to the specified pipes.
  1036.    NO_PIPE and REDIRECT_BOTH are handled correctly. */
  1037. do_piping (pipe_in, pipe_out)
  1038.      int pipe_in, pipe_out;
  1039. {
  1040.   if (pipe_in != NO_PIPE) {
  1041.     dup2 (pipe_in, 0);
  1042.     close (pipe_in);
  1043.   }
  1044.   if (pipe_out != NO_PIPE) {
  1045.     dup2 (pipe_out, 1);
  1046.     close (pipe_out);
  1047.     if (pipe_out == REDIRECT_BOTH)
  1048.       dup2 (1, 2);
  1049.   }
  1050. }
  1051.  
  1052. /* Non-zero means don't overwrite existing files. */
  1053. int noclobber = 0;
  1054.  
  1055. #define AMBIGUOUS_REDIRECT -1
  1056. #define NOCLOBBER_REDIRECT -2
  1057. /* Perform the redirections on LIST.  If FOR_REAL, then actually make
  1058.    input and output file descriptors, otherwise just do whatever is
  1059.    neccessary for side effecting.  INTERNAL says to remember how to
  1060.    undo the redirections later, if non-zero.  */
  1061. do_redirections (list, for_real, internal)
  1062.      REDIRECT *list;
  1063.      int for_real, internal;
  1064. {
  1065.   register int error;
  1066.   register REDIRECT *temp = list;
  1067.  
  1068.   if (internal && redirection_undo_list)
  1069.     {
  1070.       dispose_redirects (redirection_undo_list);
  1071.       redirection_undo_list = (REDIRECT *)NULL;
  1072.     }
  1073.  
  1074.   while (temp)
  1075.     {
  1076.       error = do_redirection (temp, for_real, internal);
  1077.       if (error)
  1078.     {
  1079.       if (error == AMBIGUOUS_REDIRECT)
  1080.         report_error ("%s: Ambiguous redirect",
  1081.               temp->redirectee.filename->word);
  1082.       else if (error == NOCLOBBER_REDIRECT)
  1083.         report_error ("%s: Cannot clobber existing file\n",
  1084.               temp->redirectee.filename->word);
  1085.       else
  1086.         report_error ("%s: %s",
  1087.               temp->redirectee.filename->word,
  1088.               sys_errlist[error]);
  1089.       return (error);
  1090.     }
  1091.  
  1092.       temp = temp->next;
  1093.     }
  1094.   return (0);
  1095. }
  1096.  
  1097.  
  1098.  
  1099. /* Expand the word in WORD returning a string.  If WORD expands to
  1100.    multiple words (or no words), then return NULL. */
  1101. char *
  1102. redirection_expand (word)
  1103.      WORD_DESC *word;
  1104. {
  1105.   char *string_list (), *result;
  1106.   WORD_LIST *make_word_list (), *expand_words_no_vars ();
  1107.   WORD_LIST *tlist1, *tlist2;
  1108.  
  1109.   tlist1 = make_word_list (copy_word (word), (WORD_LIST *)NULL);
  1110.   tlist2 = expand_words_no_vars (tlist1);
  1111.   dispose_words (tlist1);
  1112.  
  1113.   result = string_list (tlist2);
  1114.   dispose_words (tlist2);
  1115.   return (result);
  1116. }
  1117.  
  1118. /* Do the specific redirection requested.  Returns errno in case of error.
  1119.    If FOR_REAL is zero, then just do whatever is neccessary to produce the
  1120.    appropriate side effects.   REMEMBERING, if non-zero, says to remember
  1121.    how to undo each redirection.  */
  1122. do_redirection (redirect, for_real, remembering)
  1123.      REDIRECT *redirect;
  1124.      int for_real, remembering;
  1125. {
  1126.   WORD_DESC *redirectee = redirect->redirectee.filename;
  1127.   int redirector = redirect->redirector;
  1128.   char *redirectee_word = 0;
  1129.   enum r_instruction ri = redirect->instruction;
  1130.  
  1131.   int fd;
  1132.  
  1133.   switch (ri)
  1134.     {
  1135.     case r_output_direction:
  1136.     case r_appending_to:
  1137.     case r_input_direction:
  1138.     case r_inputa_direction:
  1139.     case r_err_and_out:        /* command &>filename */
  1140.  
  1141.       if (!(redirectee_word = redirection_expand (redirectee)))
  1142.     return (AMBIGUOUS_REDIRECT);
  1143.  
  1144.       /* If we are in noclobber mode, you are not allowed to overwrite
  1145.      existing files.  Check first. */
  1146.       if (noclobber && (ri == r_output_direction ||
  1147.             ri == r_appending_to ||
  1148.             ri == r_err_and_out))
  1149.     {
  1150.       struct stat buf;
  1151.       if (stat (redirectee_word, &buf) == 0)
  1152.         return (NOCLOBBER_REDIRECT);
  1153.     }
  1154.  
  1155.       fd = open (redirectee_word, redirect->flags, 0666);
  1156.       free (redirectee_word);
  1157.  
  1158.       if (fd < 0 )
  1159.     return (errno);
  1160.  
  1161.       if (for_real)
  1162.     {
  1163.       struct stat buf;
  1164.  
  1165.       if (remembering)
  1166.         /* Only setup to undo it if the thing to undo is active. */
  1167.         if (fstat (redirector, &buf) == 0)
  1168.           add_undo_redirect (redirector);
  1169.  
  1170.       if (fd != redirector && dup2 (fd, redirector) < 0)
  1171.         return (errno);
  1172.     }
  1173.       if (fd != redirector)
  1174.     close (fd);
  1175.  
  1176.       /* If we are hacking both stdout and stderr, do the stderr
  1177.      redirection here. */
  1178.       if (redirect->instruction == r_err_and_out)
  1179.     {
  1180.       if (for_real)
  1181.         {
  1182.           if (remembering)
  1183.         add_undo_redirect (2);
  1184.           dup2 (1, 2);
  1185.         }
  1186.     }
  1187.       break;
  1188.  
  1189.     case r_reading_until:
  1190.     case r_deblank_reading_until:
  1191.       {
  1192.     /* REDIRECTEE is a pointer to a WORD_DESC containing the text of
  1193.        the new input.  Place it in a temporary file. */
  1194.     char *document = (char *)NULL;
  1195.     int document_index = 0;
  1196.  
  1197.     /* Expand the text if the word that was specified had no quoting.
  1198.        Note that the text that we expand is treated exactly as if it
  1199.        were surrounded by double-quotes.  */
  1200.     
  1201.     if (!redirectee)
  1202.       document = savestring ("");
  1203.     else
  1204.       {
  1205.         if (!redirectee->quoted)
  1206.           {
  1207.         WORD_LIST *temp_word_list =
  1208.           (WORD_LIST *)expand_string (redirectee->word, 1);
  1209.  
  1210.         document = (char *)string_list (temp_word_list);
  1211.         if (!document)
  1212.           document = savestring ("");
  1213.         dispose_words (temp_word_list);
  1214.           }
  1215.         else
  1216.           {
  1217.         document = redirectee->word;
  1218.           }
  1219.         document_index = strlen (document);
  1220.  
  1221.         {
  1222.           char filename[40];
  1223.           int pid = getpid ();
  1224.  
  1225.           /* Make the filename for the temp file. */
  1226.           sprintf (filename, "/tmp/t%d-sh", pid);
  1227.     
  1228.           fd = open (filename, O_TRUNC | O_WRONLY | O_CREAT, 0666);
  1229.           if (fd < 0)
  1230.         {
  1231.           if (!redirectee->quoted)
  1232.             free (document);
  1233.           return (errno);
  1234.         }
  1235.           write (fd, document, document_index);
  1236.           close (fd);
  1237.           if (!redirectee->quoted)
  1238.         free (document);
  1239.  
  1240.           /* Make the document really temporary.  Also make it the
  1241.          input. */
  1242.           fd = open (filename, O_RDONLY, 0666);
  1243.  
  1244.           if (unlink (filename) < 0 || fd < 0)
  1245.         return (errno);
  1246.  
  1247.           if (for_real)
  1248.         {
  1249.           if (remembering)
  1250.             add_undo_redirect (redirector);
  1251.  
  1252.           if (dup2 (fd, redirector) < 0)
  1253.             return (errno);
  1254.         }
  1255.           close (fd);
  1256.         }
  1257.       }
  1258.       }
  1259.       break;
  1260.  
  1261.     case r_duplicating:
  1262.       if (for_real)
  1263.     {
  1264.       if (remembering)
  1265.         add_undo_redirect (redirector);
  1266.  
  1267.       /* This is correct.  2>&1 means dup2 (1, 2); */
  1268.       dup2 ((int)redirectee, redirector);
  1269.     }
  1270.       break;
  1271.  
  1272.     case r_close_this:
  1273.       if (for_real)
  1274.     {
  1275.       if (remembering)
  1276.         add_undo_redirect (redirector);
  1277.       close (redirector);
  1278.     }
  1279.       break;
  1280.     }
  1281.   return (0);
  1282. }
  1283.  
  1284. /* Remember the file descriptor associated with the slot FD,
  1285.    on REDIRECTION_UNDO_LIST.  Note that the list will be reversed
  1286.    before it is executed. */
  1287. add_undo_redirect (fd)
  1288.      int fd;
  1289. {
  1290.   int new_fd = dup (fd);
  1291.   REDIRECT *new_redirect, *closer;
  1292.  
  1293.   if (new_fd < 0)
  1294.     {
  1295.       file_error ("redirection error");
  1296.       return (-1);
  1297.     }
  1298.   else
  1299.     {
  1300.       closer = make_redirection (new_fd, r_close_this, 0);
  1301.       new_redirect = make_redirection (fd, r_duplicating, new_fd);
  1302.       new_redirect->next = closer;
  1303.       closer->next = redirection_undo_list;
  1304.       redirection_undo_list = new_redirect;
  1305.     }
  1306.   return (0);
  1307. }
  1308.   
  1309. intern_function (name, function)
  1310.      WORD_DESC *name;
  1311.      COMMAND *function;
  1312. {
  1313.   if (!check_identifier (name))
  1314.     return (EXECUTION_FAILURE);
  1315.   bind_function (name->word, function);
  1316.   return (EXECUTION_SUCCESS);
  1317. }
  1318.  
  1319. /* Make sure that identifier is a valid shell identifier, i.e.
  1320.    does not contain a dollar sign, nor is quoted in any way.  Nor
  1321.    does it consist of all digits. */
  1322. check_identifier (word)
  1323.      WORD_DESC *word;
  1324. {
  1325.   if (word->dollar_present || word->quoted || all_digits (word->word)) {
  1326.     report_error ("`%s' is not a valid identifier", word->word);
  1327.     return (0);
  1328.   } else return (1);
  1329. }
  1330.  
  1331. all_digits (string)
  1332.      char *string;
  1333. {
  1334.   while (*string) {
  1335.     if (!digit (*string)) return (0);
  1336.     else string++;
  1337.   }
  1338.   return (1);
  1339. }
  1340.  
  1341. #define u_mode_bits(x) (((x) & 0000700) >> 6)
  1342. #define g_mode_bits(x) (((x) & 0000070) >> 3)
  1343. #define o_mode_bits(x) (((x) & 0000007) >> 0)
  1344. #define X_BIT(x) (x & 1)
  1345.  
  1346. /* Non-zero if the last call to executable_file () found
  1347.    the file, but stated that it wasn't executable. */
  1348. int file_exists_p = 0;
  1349.  
  1350. /* Return non-zero if FILE is an executable file, otherwise 0.
  1351.    Note that this function is the definition of what an
  1352.    executable file is; do not change this unless YOU know
  1353.    what an executable file is. */
  1354. executable_file (file)
  1355.      char *file;
  1356. {
  1357.   struct stat finfo;
  1358.   int user_id;
  1359.  
  1360.   /* If the file doesn't exist, or is a directory, then we are
  1361.      not interested. */
  1362.   file_exists_p = !stat (file, &finfo);
  1363.   if (!file_exists_p || (finfo.st_mode & S_IFDIR))
  1364.     return (0);
  1365.  
  1366.   /* By definition, the only other criteria is that the file has
  1367.      an execute bit set that we can use. */
  1368.   user_id = geteuid ();
  1369.  
  1370.   /* If we are the owner of the file, the owner execute bit applies. */
  1371.   if (user_id == finfo.st_uid)
  1372.     return (X_BIT (u_mode_bits (finfo.st_mode)));
  1373.  
  1374.   /* If we are in the owning group, the group permissions apply. */
  1375.   if (group_member (finfo.st_gid))
  1376.     return (X_BIT (g_mode_bits (finfo.st_mode)));
  1377.  
  1378.   /* If `others' have execute permission to the file, then so do we,
  1379.      since we are also `others'. */
  1380.   return (X_BIT (o_mode_bits (finfo.st_mode)));
  1381. }
  1382.  
  1383. #ifndef SYSV
  1384. /* The number of groups (within 64) that this user is a member of. */
  1385. static int default_group_array_size = 0;
  1386. static int ngroups = 0;
  1387. static int *group_array = (int *)NULL;
  1388. #endif
  1389.  
  1390. /* Return non-zero if GID is one that we have in our groups list. */
  1391. group_member (gid)
  1392.      int gid;
  1393. {
  1394. #ifdef SYSV
  1395.   return ((gid == getgid ()) || (gid == geteuid ()));
  1396. #else
  1397.  
  1398.   register int i;
  1399.  
  1400.   /* getgroups () returns the number of elements that it was able to
  1401.      place into the array.  We simply continue to call getgroups ()
  1402.      until the number of elements placed into the array is smaller than
  1403.      the physical size of the array. */
  1404.  
  1405.   while (ngroups == default_group_array_size)
  1406.     {
  1407.       default_group_array_size += 64;
  1408.  
  1409.       if (!group_array)
  1410.     group_array = (int *)xmalloc (default_group_array_size * sizeof (int));
  1411.       else
  1412.     group_array =
  1413.       (int *)xrealloc (group_array,
  1414.                default_group_array_size * sizeof (int));
  1415.  
  1416.       ngroups = getgroups (default_group_array_size, group_array);
  1417.     }
  1418.  
  1419.   /* In case of error, the user loses. */
  1420.   if (ngroups < 0)
  1421.     return (0);
  1422.  
  1423.   /* Search through the list looking for GID. */
  1424.   for (i = 0; i < ngroups; i++)
  1425.     if (gid == group_array[i])
  1426.       return (1);
  1427.  
  1428.   return (0);
  1429. #endif  /* SYSV */
  1430. }
  1431.  
  1432. /* DOT_FOUND_IN_SEARCH becomes non-zero when find_user_command ()
  1433.    encounters a `.' as the directory pathname while scanning the
  1434.    list of possible pathnames; i.e., if `.' comes before the directory
  1435.    containing the file of interest. */
  1436. int dot_found_in_search = 0;
  1437.  
  1438. /* Locate the executable file referenced by NAME, searching along
  1439.    the contents of the shell PATH variable.
  1440.    Return a new string which is the full pathname to the file,
  1441.    or NULL if the file couldn't be found.
  1442.    If a file is found that isn't executable, and that is the only
  1443.    match, then return that. */
  1444. char *
  1445. find_user_command (name)
  1446.      char *name;
  1447. {
  1448.   char *find_user_command_internal ();
  1449.  
  1450.   return (find_user_command_internal (name, 1));
  1451. }
  1452.  
  1453. /* Locate the file referenced by NAME, searching along
  1454.    the contents of the shell PATH variable.
  1455.    Return a new string which is the full pathname to the file,
  1456.    or NULL if the file couldn't be found.
  1457.    This returns the first file found. */
  1458. char *
  1459. find_path_file (name)
  1460.      char *name;
  1461. {
  1462.   char *find_user_command_internal ();
  1463.  
  1464.   return (find_user_command_internal (name, 0));
  1465. }
  1466.  
  1467. char *
  1468. find_user_command_internal (name, must_be_executable)
  1469.      char *name;
  1470.      int must_be_executable;
  1471. {
  1472.   char *path_list;
  1473.   char *find_user_command_in_path ();
  1474.  
  1475.   path_list = get_string_value ("PATH");
  1476.   if (!path_list) return (savestring (name));
  1477.  
  1478.   return (find_user_command_in_path (name, path_list, must_be_executable));
  1479. }
  1480.  
  1481. char *
  1482. user_command_matches (name, must_be_executable, state)
  1483.      char *name;
  1484.      int must_be_executable;
  1485.      int state;
  1486. {
  1487.   register int i;
  1488.   char *path_list;
  1489.   int  path_index;
  1490.   char *path_element;
  1491.   char *match;
  1492.   static char **match_list = NULL;
  1493.   static int match_list_size = 0;
  1494.   static int match_index = 0;
  1495.   char *extract_colon_unit ();
  1496.   
  1497.   if (!state)
  1498.     {
  1499.       /* Create the list of matches. */
  1500.       if (!match_list)
  1501.     {
  1502.       match_list = 
  1503.         (char **) xmalloc ((match_list_size = 5) * sizeof(char *));
  1504.  
  1505.       for (i = 0; i < match_list_size; i++)
  1506.         match_list[i] = 0;
  1507.     }
  1508.       
  1509.       /* Clear out the old match list. */
  1510.       for (i = 0; i < match_list_size; i++)
  1511.     match_list[i] = NULL;
  1512.  
  1513.       /* We haven't found any files yet. */
  1514.       match_index = 0;
  1515.  
  1516.       path_list = get_string_value ("PATH");
  1517.       path_index = 0;
  1518.  
  1519.       while (path_element = extract_colon_unit (path_list, &path_index))
  1520.     {
  1521.       char *find_user_command_in_path ();
  1522.  
  1523.       match =
  1524.         find_user_command_in_path (name, path_element, must_be_executable);
  1525.  
  1526.       free (path_element);
  1527.  
  1528.       if (!match)
  1529.         continue;
  1530.       
  1531.       if (match_index + 1 == match_list_size)
  1532.         match_list =
  1533.           (char **)xrealloc (match_list,
  1534.                  ((match_list_size += 10) + 1) * sizeof (char *));
  1535.       match_list[match_index++] = match;
  1536.       match_list[match_index] = (char *)NULL;
  1537.     }
  1538.  
  1539.       /* We haven't returned any strings yet. */
  1540.       match_index = 0;
  1541.     }
  1542.  
  1543.   match = match_list[match_index];
  1544.  
  1545.   if (match)
  1546.     match_index++;
  1547.  
  1548.   return(match);
  1549. }
  1550.  
  1551. /* This does the dirty work for find_path_file ()
  1552.    and find_user_command (). */
  1553. char *
  1554. find_user_command_in_path (name, path_list, must_be_executable)
  1555.      char *name;
  1556.      char *path_list;
  1557.      int must_be_executable;
  1558. {
  1559.   extern char *extract_colon_unit ();
  1560.   extern int file_exists_p;
  1561.   char *full_path;
  1562.   char *path;
  1563.   int path_index = 0;
  1564.  
  1565.   /* The file name which we would try to execute, except that it isn't
  1566.      possible to execute it.  This is the first file that matches the
  1567.      name that we are looking for while we are searching $PATH for a
  1568.      suitable one to execute.  If we cannot find a suitable executable
  1569.      file, then we use this one. */
  1570.   char *file_to_lose_on = (char *)NULL;
  1571.  
  1572.   /* We haven't started looking, so we certainly haven't seen
  1573.      a `.' as the directory path yet. */
  1574.   dot_found_in_search = 0;
  1575.  
  1576.   if (absolute_pathname (name))
  1577.     {
  1578.       full_path = (char *)xmalloc (1 + strlen (name));
  1579.       strcpy (full_path, name);
  1580.  
  1581.       if (executable_file (full_path) || file_exists_p)
  1582.     {
  1583.       return (full_path);
  1584.     }
  1585.       else
  1586.     {
  1587.       free (full_path);
  1588.       return ((char *)NULL);
  1589.     }
  1590.     }
  1591.  
  1592.   while (path_list && path_list[path_index])
  1593.     {
  1594.       path = extract_colon_unit (path_list, &path_index);
  1595.       if (!*path || !*path)
  1596.     {
  1597.       free (path);
  1598.       path = savestring ("."); /* by definition. */
  1599.     }
  1600.  
  1601.       if (!disallow_filename_globbing && *path == '~')
  1602.     {
  1603.       char *tilde_expand ();
  1604.       char *t = tilde_expand (path);
  1605.       free (path);
  1606.       path = t;
  1607.     }
  1608.  
  1609.       /* Remember the location of "." in the path. */
  1610.       if (strcmp (path, ".") == 0)
  1611.     dot_found_in_search = 1;
  1612.  
  1613.       full_path = (char *)xmalloc (2 + strlen (path) + strlen (name));
  1614.       sprintf (full_path, "%s/%s", path, name);
  1615.       free (path);
  1616.  
  1617.       if (executable_file (full_path) ||
  1618.       (!must_be_executable && file_exists_p))
  1619.     {
  1620.       if (file_to_lose_on)
  1621.         free (file_to_lose_on);
  1622.       return (full_path);
  1623.     }
  1624.       else
  1625.     {
  1626.       if (file_exists_p && !file_to_lose_on)
  1627.         file_to_lose_on = full_path;
  1628.       else
  1629.         free (full_path);
  1630.     }
  1631.     }
  1632.   /* If we found a file with the right name, but not one that is
  1633.      executable, then return the one with the right name. */
  1634.   if (file_to_lose_on)
  1635.     return (file_to_lose_on);
  1636.   else
  1637.     return (char *)NULL;
  1638. }
  1639.  
  1640. /* Given a string containing units of information separated by colons,
  1641.    return the next one pointed to by INDEX, or NULL if there are no more.
  1642.    Advance INDEX to the character after the colon. */
  1643. char *
  1644. extract_colon_unit (string, index)
  1645.      char *string;
  1646.      int *index;
  1647. {
  1648.   int i, start;
  1649.  
  1650.   i = *index;
  1651.  
  1652.   if ((i >= strlen (string)) || !string)
  1653.     return ((char *)NULL);
  1654.  
  1655.   if (string[i] == ':')
  1656.     i++;
  1657.  
  1658.   start = i;
  1659.  
  1660.   while (string[i] && string[i] != ':') i++;
  1661.  
  1662.   *index = i;
  1663.  
  1664.   if (i == start)
  1665.     {
  1666.       if (!string[i])
  1667.     return ((char *)NULL);
  1668.  
  1669.       (*index)++;
  1670.  
  1671.       return (savestring (""));
  1672.     }
  1673.   else
  1674.     {
  1675.       char *value;
  1676.  
  1677.       value = (char *)xmalloc (1 + (i - start));
  1678.       strncpy (value, &string[start], (i - start));
  1679.       value [i - start] = '\0';
  1680.  
  1681.       return (value);
  1682.     }
  1683. }
  1684.